package com.heima.wemedia.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.heima.common.constants.WemediaConstants;
import com.heima.common.constants.WmNewsMessageConstants;
import com.heima.common.dtos.PageResponseResult;
import com.heima.common.dtos.ResponseResult;
import com.heima.common.enums.AppHttpCodeEnum;
import com.heima.common.exception.CustomException;
import com.heima.model.common.msg.UpDownMsg;
import com.heima.model.wemedia.dtos.NewsDto;
import com.heima.model.wemedia.dtos.WmNewsDto;
import com.heima.model.wemedia.dtos.WmNewsPageReqDto;
import com.heima.model.wemedia.pojos.WmMaterial;
import com.heima.model.wemedia.pojos.WmNews;
import com.heima.model.wemedia.pojos.WmNewsMaterial;
import com.heima.wemedia.mapper.WmNewsMapper;
import com.heima.wemedia.mapper.WmNewsMaterialMapper;
import com.heima.wemedia.service.WmMaterialService;
import com.heima.wemedia.service.WmNewsAutoScanService;
import com.heima.wemedia.service.WmNewsService;
import com.heima.wemedia.util.WmThreadLocal;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
@Service
public class WmNewsServiceImpl extends ServiceImpl<WmNewsMapper, WmNews> implements WmNewsService {
    @Resource
    private WmNewsMaterialMapper wmNewsMaterialMapper;
    @Resource
    private WmMaterialService wmMaterialServicel;
    @Resource
    private KafkaTemplate<String, String> kafkaTemplate;
    @Resource
    private WmNewsAutoScanService wmNewsAutoScanService;
    @Override
    public ResponseResult<List<WmNews>> findAll(WmNewsPageReqDto dto) {
        Page<WmNews> p = new Page<>(dto.getPage(), dto.getSize());

        Page<WmNews> page = lambdaQuery()
                .like(dto.getKeyword() != null, WmNews::getTitle, dto.getKeyword())
                .eq(dto.getStatus() != null, WmNews::getStatus, dto.getStatus())
                .eq(dto.getChannelId() != null, WmNews::getChannelId, dto.getChannelId())
                .between(ObjectUtil.isNotEmpty(dto.getBeginPubDate()) || ObjectUtil.isNotEmpty(dto.getEndPubDate()), WmNews::getPublishTime, dto.getBeginPubDate(), dto.getEndPubDate())
                .page(p);

        return PageResponseResult.<List<WmNews>>builder()
                .currentPage(dto.getPage())
                .size(dto.getSize())
                .total(Convert.toInt(page.getTotal()))
                .data(page.getRecords())
                .build();
    }

    @Override
    public ResponseResult<Object> submitNews(WmNewsDto dto) {
        if (ObjectUtil.isEmpty(dto.getContent())){
            return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST);
        }
        WmNews wmNews = BeanUtil.toBean(dto, WmNews.class);
        // 更新或新增操作
        if (ObjectUtil.equals(dto.getType(), WemediaConstants.WM_NEWS_TYPE_AUTO)){
            wmNews.setType(null);
        }

        if (ObjectUtil.isNotEmpty(dto.getImages())){
            List<String> images = dto.getImages();
            String image = CollUtil.join(images, ",");
            wmNews.setImages(image);
        }
        // 新增或更新文章
        saveOrUpdateNews(wmNews);
        // 如果文章的状态为存稿，直接返回
        if (ObjectUtil.equals(dto.getStatus(), WmNews.Status.NORMAL.getCode())){
            return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
        }
        // 获取文章内容中的全部图片
        String content = wmNews.getContent();
        List<String> contentImage = getContentImage(content);
        // 添加关联
        addWmNewsMateria(contentImage, wmNews, WemediaConstants.WM_CONTENT_REFERENCE);
        // 如果文章布局为自动，则从文章内容的图片抽出来作封面
        if (ObjectUtil.equals(dto.getType(), WemediaConstants.WM_NEWS_TYPE_AUTO)){
            List<String> images = dto.getImages();
            // 如果文章图片大于等于三张，则将文章布局设为多图
            if (contentImage.size() >= 3){
                wmNews.setType(WemediaConstants.WM_NEWS_MANY_IMAGE);
                CollUtil.addAll(images, CollUtil.sub(contentImage, 0, 4));
            }
            // 如果文章图片少于三张，则将文章布局设为单图
            if (contentImage.size() > 0 && contentImage.size() <= 2){
                wmNews.setType(WemediaConstants.WM_NEWS_SINGLE_IMAGE);
                CollUtil.addAll(images, CollUtil.sub(contentImage, 0, 1));
            }
            // 如果文章有图片，将文章图片当做封面图，添加新闻素材关联
            addWmNewsMateria(images, wmNews,WemediaConstants.WM_COVER_REFERENCE);
            // 如果文章没有图片，则将文章布局设为无图
            if (ObjectUtil.isEmpty(contentImage)){
                wmNews.setType(WemediaConstants.WM_NEWS_NONE_IMAGE);
            }
            // 更新新闻信息
            updateById(wmNews);
        } else {
            addWmNewsMateria(dto.getImages(), wmNews, WemediaConstants.WM_COVER_REFERENCE);
        }
        wmNewsAutoScanService.autoScanWmNews(wmNews.getId());

        return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
    }

    public void addWmNewsMateria(List<String> images, WmNews wmNews, Short type){
        // 判断图片信息是否为空
        if (CollUtil.isNotEmpty(images)){
            // 根据图片地址获取素材信息集合
            List<WmMaterial> wmMaterials = wmMaterialServicel.lambdaQuery().in(WmMaterial::getUrl, images).list();
            // 如果为空，直接抛异常
            if (ObjectUtil.isEmpty(wmMaterials)){
                throw new CustomException(AppHttpCodeEnum.DATA_NOT_EXIST);
            }
            // 如果素材集合大小和图片集合大小不相符，也抛异常
            if (ObjectUtil.notEqual(images.size(), wmMaterials.size())){
                throw new CustomException(AppHttpCodeEnum.SERVER_ERROR);
            }
            // 获取素材id集合
            List<Integer> ids = new ArrayList<>();
            wmMaterials.forEach(wmMaterial -> ids.add(wmMaterial.getId()));
            // 将素材与新闻的关联信息插入表中
            WmNewsMaterial wmNewsMaterial = new WmNewsMaterial();
            wmNewsMaterial.setType(type);
            wmNewsMaterial.setNewsId(wmNews.getId());
            for (Integer id : ids) {
                wmNewsMaterial.setMaterialId(id);
                wmNewsMaterialMapper.insert(wmNewsMaterial);
                wmNewsMaterial.setId(null);
            }
        }
    }

    private List<String> getContentImage(String content) {
        List<JSONObject> list = JSONUtil.toList(content, JSONObject.class);
        List<String> images = new ArrayList<>();

        for (JSONObject object : list) {
            if (StrUtil.equals(object.getStr("type"), "image")){
                images.add(Convert.toStr(object.get("value")));
            }
        }
        return images;
    }

    private void saveOrUpdateNews(WmNews wmNews) {
        if (ObjectUtil.equals(wmNews.getId(), null)){
            // 填充信息
            wmNews.setUserId(WmThreadLocal.getUser().getId());
            wmNews.setCreatedTime(new Date());
            if (ObjectUtil.equals(wmNews.getStatus(), Convert.toShort(1))){
                wmNews.setSubmitedTime(new Date());
            }
            save(wmNews);
            return;
        }
        // 更新操作
        // 构造删除材料的条件
        QueryWrapper<WmNewsMaterial> wrapper = new QueryWrapper<>();
        wrapper.eq("news_id", wmNews.getId());
        // 删除材料信息
        wmNewsMaterialMapper.delete(wrapper);
        updateById(wmNews);
    }

    @Override
    public ResponseResult<Object> delNews(Integer id) {
        if (ObjectUtil.isEmpty(id)){
            return ResponseResult.errorResult(501, "文章Id不可缺少");
        }
        WmNews wmNews = this.getById(id);
        if (ObjectUtil.isEmpty(wmNews)){
            return ResponseResult.errorResult(1002, "文章不存在");
        }
        if (ObjectUtil.equals(wmNews.getStatus(), Convert.toShort(9))){
            return ResponseResult.errorResult(501, "文章已发布，不能删除");
        }

        wmNewsMaterialMapper.delete(new QueryWrapper<WmNewsMaterial>().eq("news_id", id));
        removeById(id);
        return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
    }

    @Override
    public ResponseResult<Object> DownOrUpNews(NewsDto newsDto) {
        if (ObjectUtil.isEmpty(newsDto.getId())){
            return ResponseResult.errorResult(501, "文章Id不可缺少");
        }
        WmNews wmNews = this.getById(newsDto.getId());
        if (ObjectUtil.isEmpty(wmNews)){
            return ResponseResult.errorResult(1002, "文章不存在");
        }
        if (!ObjectUtil.equals(wmNews.getStatus(), Convert.toShort(9))){
            return ResponseResult.errorResult(501, "当前文章不是发布状态，不能上下架");
        }
        wmNews.setEnable(newsDto.getEnable());
        updateById(wmNews);
        if (ObjectUtil.isNotEmpty(wmNews.getArticleId())){
            UpDownMsg upDownMsg = UpDownMsg.builder()
                    .articleId(wmNews.getArticleId())
                    .enable(wmNews.getEnable())
                    .build();
            kafkaTemplate.send(WmNewsMessageConstants.WM_NEWS_UP_OR_DOWN_TOPIC, JSONUtil.toJsonStr(upDownMsg));
            System.out.println(JSONUtil.toJsonStr(upDownMsg));
        }
        return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
    }
}
